﻿using System;
using System.Collections.Generic;
using System.Text;

namespace SeleniumOrderPathRunner {
    [Serializable]
    public class TestAssertionException: System.Exception {

        public enum AssertionTypeEnum { NoType, Exist, NotExist, HasAttribute, NotHasAttribute, AtLocation, HasText , NotHasText, HasCSS, NotHasCSS};

        private LinkedList<String> assertionData;
        private AssertionTypeEnum assertionType;

        public LinkedList<String> AssertionData { get { return assertionData; } }
        public AssertionTypeEnum AssertionType { get { return assertionType; } }

        public override string Message {
            get {
                //if user throws exception with a custom data, use that. Otherwise, use regular message
                if (assertionData.Count > 0) {
                    String customMessage = "AssertionException: ";
                    customMessage += Enum.GetName(typeof(AssertionTypeEnum), assertionType) + Environment.NewLine;
                    foreach(String s in AssertionData){
                        customMessage += " " + s + Environment.NewLine;
                    }
                    return customMessage;
                }
                return base.Message;
            }
        }


        /// <summary>
        /// Only for use in the textCompare asserts. Not needed for the exist asserts so it isn't designed to handle them.
        /// </summary>
        /// <param name="sT"></param>
        /// <param name="tT"></param>
        /// <param name="cT">Content types do not contain the exist types, so don't use this for them. Shouldn't be necessary anyhow</param>
        public TestAssertionException(AugmentedSelenium.Set sT, AugmentedSelenium.Compare tT, AugmentedSelenium.TextContentType cT): base() {
            switch (sT) {
                case AugmentedSelenium.Set.All:
                switch (cT) {
                    case AugmentedSelenium.TextContentType.LocatorAttribute:
                    if (tT == AugmentedSelenium.Compare.Is || tT == AugmentedSelenium.Compare.Has) {
                        assertionType = AssertionTypeEnum.HasAttribute;
                    } else {
                        assertionType = AssertionTypeEnum.NotHasAttribute;
                    }
                    break;
                    case AugmentedSelenium.TextContentType.LocatorText:
                    if (tT == AugmentedSelenium.Compare.Is || tT == AugmentedSelenium.Compare.Has) {
                        assertionType = AssertionTypeEnum.HasText;
                    } else {
                        assertionType = AssertionTypeEnum.NotHasText;
                    }
                    break;
                    case AugmentedSelenium.TextContentType.SelectorProperty:
                    if (tT == AugmentedSelenium.Compare.Is || tT == AugmentedSelenium.Compare.Has) {
                        assertionType = AssertionTypeEnum.HasCSS;
                    } else {
                        assertionType = AssertionTypeEnum.NotHasCSS;
                    }
                    break;
                }
                break;
                case AugmentedSelenium.Set.AllNone://arbitrarily pick has
                switch (cT) {
                    case AugmentedSelenium.TextContentType.LocatorAttribute:
                    if (tT == AugmentedSelenium.Compare.Is || tT == AugmentedSelenium.Compare.Has) {
                        assertionType = AssertionTypeEnum.HasAttribute;
                    } else {
                        assertionType = AssertionTypeEnum.NotHasAttribute;
                    }
                    break;
                    case AugmentedSelenium.TextContentType.LocatorText:
                    if (tT == AugmentedSelenium.Compare.Is || tT == AugmentedSelenium.Compare.Has) {
                        assertionType = AssertionTypeEnum.HasText;
                    } else {
                        assertionType = AssertionTypeEnum.NotHasText;
                    }
                    break;
                    case AugmentedSelenium.TextContentType.SelectorProperty:
                    if (tT == AugmentedSelenium.Compare.Is || tT == AugmentedSelenium.Compare.Has) {
                        assertionType = AssertionTypeEnum.HasCSS;
                    } else {
                        assertionType = AssertionTypeEnum.NotHasCSS;
                    }
                    break;
                }
                break;
                case AugmentedSelenium.Set.AllSome:
                switch (cT) {
                    case AugmentedSelenium.TextContentType.LocatorAttribute:
                    if (tT == AugmentedSelenium.Compare.Is || tT == AugmentedSelenium.Compare.Has) {
                        assertionType = AssertionTypeEnum.HasAttribute;
                    } else {
                        assertionType = AssertionTypeEnum.NotHasAttribute;
                    }
                    break;
                    case AugmentedSelenium.TextContentType.LocatorText:
                    if (tT == AugmentedSelenium.Compare.Is || tT == AugmentedSelenium.Compare.Has) {
                        assertionType = AssertionTypeEnum.HasText;
                    } else {
                        assertionType = AssertionTypeEnum.NotHasText;
                    }
                    break;
                    case AugmentedSelenium.TextContentType.SelectorProperty:
                    if (tT == AugmentedSelenium.Compare.Is || tT == AugmentedSelenium.Compare.Has) {
                        assertionType = AssertionTypeEnum.HasCSS;
                    } else {
                        assertionType = AssertionTypeEnum.NotHasCSS;
                    }
                    break;
                }
                break;
                case AugmentedSelenium.Set.None:
                switch (cT) {
                    case AugmentedSelenium.TextContentType.LocatorAttribute:
                    if (tT == AugmentedSelenium.Compare.Is || tT == AugmentedSelenium.Compare.Has) {
                        assertionType = AssertionTypeEnum.NotHasAttribute;
                    } else {
                        assertionType = AssertionTypeEnum.HasAttribute;
                    }
                    break;
                    case AugmentedSelenium.TextContentType.LocatorText:
                    if (tT == AugmentedSelenium.Compare.Is || tT == AugmentedSelenium.Compare.Has) {
                        assertionType = AssertionTypeEnum.NotHasText;
                    } else {
                        assertionType = AssertionTypeEnum.HasText;
                    }
                    break;
                    case AugmentedSelenium.TextContentType.SelectorProperty:
                    if (tT == AugmentedSelenium.Compare.Is || tT == AugmentedSelenium.Compare.Has) {
                        assertionType = AssertionTypeEnum.NotHasCSS;
                    } else {
                        assertionType = AssertionTypeEnum.HasCSS;
                    }
                    break;
                }
                break;
                case AugmentedSelenium.Set.Some://arbitrarily pick has
                switch (cT) {
                    case AugmentedSelenium.TextContentType.LocatorAttribute:
                    if (tT == AugmentedSelenium.Compare.Is || tT == AugmentedSelenium.Compare.Has) {
                        assertionType = AssertionTypeEnum.HasAttribute;
                    } else {
                        assertionType = AssertionTypeEnum.NotHasAttribute;
                    }
                    break;
                    case AugmentedSelenium.TextContentType.LocatorText:
                    if (tT == AugmentedSelenium.Compare.Is || tT == AugmentedSelenium.Compare.Has) {
                        assertionType = AssertionTypeEnum.HasText;
                    } else {
                        assertionType = AssertionTypeEnum.NotHasText;
                    }
                    break;
                    case AugmentedSelenium.TextContentType.SelectorProperty:
                    if (tT == AugmentedSelenium.Compare.Is || tT == AugmentedSelenium.Compare.Has) {
                        assertionType = AssertionTypeEnum.HasCSS;
                    } else {
                        assertionType = AssertionTypeEnum.NotHasCSS;
                    }
                    break;
                }
                break;
                case AugmentedSelenium.Set.SomeNone:
                switch (cT) {
                    case AugmentedSelenium.TextContentType.LocatorAttribute:
                    if (tT == AugmentedSelenium.Compare.Is || tT == AugmentedSelenium.Compare.Has) {
                        assertionType = AssertionTypeEnum.NotHasAttribute;
                    } else {
                        assertionType = AssertionTypeEnum.HasAttribute;
                    }
                    break;
                    case AugmentedSelenium.TextContentType.LocatorText:
                    if (tT == AugmentedSelenium.Compare.Is || tT == AugmentedSelenium.Compare.Has) {
                        assertionType = AssertionTypeEnum.NotHasText;
                    } else {
                        assertionType = AssertionTypeEnum.HasText;
                    }
                    break;
                    case AugmentedSelenium.TextContentType.SelectorProperty:
                    if (tT == AugmentedSelenium.Compare.Is || tT == AugmentedSelenium.Compare.Has) {
                        assertionType = AssertionTypeEnum.NotHasCSS;
                    } else {
                        assertionType = AssertionTypeEnum.HasCSS;
                    }
                    break;
                }
                break;
            }
            assertionData = new LinkedList<string>();
        }


        public TestAssertionException(AssertionTypeEnum a): base() {
            assertionType = a;
            assertionData = new LinkedList<String>();
        }

        public TestAssertionException(AssertionTypeEnum a, LinkedList<String> aData) : base() {
            assertionType = a;
            assertionData = aData;
        }


        public TestAssertionException(String message): base(message) {
            assertionData = new LinkedList<String>();
        }

        public TestAssertionException(String message, Exception innerException): base(message, innerException) {
            assertionData = new LinkedList<String>();
        }


        public TestAssertionException(Exception innerException) : base("", innerException) {
            assertionData = new LinkedList<String>();
        }


        public TestAssertionException(System.Runtime.Serialization.SerializationInfo info, System.Runtime.Serialization.StreamingContext context): base(info, context) {

        }



        public void clearAssertionData(){
            assertionData.Clear();
        }


        public void addLineToDataTop(String s) {
            assertionData.AddFirst(s);
        }

        public void addLineToDataBottom(String s) {
            assertionData.AddLast(s);
        }
    }
}
